package me.zhengjie.modules.system.rest;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.annotation.Log;
import me.zhengjie.config.FileProperties;
import me.zhengjie.domain.LocalStorage;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.ffmpeg.FFmpegUtils;
import me.zhengjie.minio.MinioUtils;
import me.zhengjie.service.LocalStorageService;
import me.zhengjie.utils.DateTimeUtil;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.PageUtil;
import org.apache.hc.core5.http.ContentType;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItem;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

/**
 * @author xiahongbo
 * @date 2022-07-13
 **/
@Slf4j
@RestController
@RequiredArgsConstructor
@Api(tags = "上传附件")
@RequestMapping("/api/minio")
public class UploadController {

    private final LocalStorageService localStorageService;
    private final FileProperties properties;

    private Path tempDir = Paths.get(System.getProperty("java.io.tmpdir"));

    @Value("${file.windows.path}")
    private String videoFolder;

    @PostMapping(value = "/uploadImage")
    @Log("MINIO上传照片")
    @ApiOperation("MINIO上传照片")
    public ResponseEntity<Object> uploadImage (@RequestParam MultipartFile file, @RequestParam String fjlb) throws Exception {
        FileUtil.checkSize(properties.getMaxSize(), file.getSize());
        // 判断文件是否为图片
        String suffix = FileUtil.getExtensionName(file.getOriginalFilename());
        if(!FileUtil.IMAGE.equals(FileUtil.getFileType(suffix))){
            throw new BadRequestException("只能上传图片");
        }
        Map<String, String> map = MinioUtils.upload(file);

        LocalStorage localStorage = new LocalStorage(
                map.get("filename"),
                FileUtil.getFileNameNoEx(file.getOriginalFilename()),
                suffix,
                map.get("url"),
                file.getContentType(),
                FileUtil.getSize(file.getSize()),
                fjlb
        );
        localStorageService.minioCreate(localStorage);
        System.out.println("=========="+HttpStatus.CREATED);
        return new ResponseEntity<>(HttpStatus.CREATED);
    }



    @PostMapping(value = "/formatVideo")
    @Log("给上传视频转码并上传至MINIO")
    @ApiOperation("给上传视频转码并上传至MINIO")
    public ResponseEntity<Object> formatVideo (@RequestParam MultipartFile file, @RequestParam String fjlb, @RequestParam(required = false) String ywid) throws Exception {
        ywid = ywid == null ? "" : ywid;
        FileUtil.checkSize(properties.getMaxSize(), file.getSize());
        // 判断文件是否为图片
        String suffix = FileUtil.getExtensionName(file.getOriginalFilename());
        if(!FileUtil.VIDEO.equals(FileUtil.getOrgFileType(suffix))){
            throw new BadRequestException("只能上传MP4视频");
        }

        log.info("文件信息：title={}, size={}", file.getOriginalFilename(), file.getSize());

        // 原始文件名称，也就是视频的标题
        String title = file.getOriginalFilename();
        String fileName = title.substring(0, title.lastIndexOf("."));

        // io到临时文件
        Path tempFile = tempDir.resolve(title);
        log.info("io到临时文件：{}", tempFile.toString());

        file.transferTo(tempFile);


        // 按照日期生成子目录
        String today = DateTimeUtil.getDate().replaceAll("-", "");
        // 删除后缀
        String newTitle = fileName + "-" + DateTimeUtil.getDateTime(DateTimeUtil.getNow(), "yyyyMMddHHmmssSSS");


        String targetFolder = Paths.get(videoFolder, today, newTitle).toString();
        // getCanonicalFile 可解析正确各种路径
        File dest = new File(targetFolder).getCanonicalFile();
        // 检测是否存在目录
        if (!dest.exists()) {
            if (!dest.mkdirs()) {
                System.out.println("was not successful.");
            }
        }

        // 尝试创建视频目录
        // Path targetFolder = Files.createDirectories(Paths.get(videoFolder, today, title));

        log.info("创建文件夹目录：{}", targetFolder);
        targetFolder = targetFolder.toString()+"\\" + title;
        log.info("创建文件夹目录：{}", targetFolder);
        // Files.createDirectories(targetFolder);

        // 执行转码操作
        log.info("开始转码");
        try {
            FFmpegUtils.audioByVideo(tempFile.toString(), targetFolder);
        } catch (Exception e) {
            log.error("转码异常：{}", e.getMessage());
            Map<String, Object> result = new HashMap<>();
            result.put("success", false);
            result.put("message", e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }

        File targetFile = new File(targetFolder);

        //MultipartFile cMultiFile = new MockMultipartFile(fileName, file.getName(), null, new FileInputStream(targetFile));
        FileInputStream fileInputStream = new FileInputStream(targetFile);
        MultipartFile cMultiFile = new MockMultipartFile(targetFile.getName(), targetFile.getName(),
                file.getContentType(), fileInputStream);

        Map<String, String> map = MinioUtils.upload(cMultiFile);

        LocalStorage localStorage = new LocalStorage(
                map.get("filename"),
                FileUtil.getFileNameNoEx(file.getOriginalFilename()),
                suffix,
                map.get("url"),
                file.getContentType(),
                FileUtil.getSize(file.getSize()),
                fjlb,
                ywid,
                map.get("url2"),
                map.get("url3")
        );
        // 始终删除临时文件
        Files.delete(tempFile);
        Files.delete(targetFile.toPath());

        LocalStorage localStorage1 = localStorageService.minioCreate(localStorage);
        map.put("id", String.valueOf(localStorage1.getId()));
        Map<String,Object> rsMap = PageUtil.toMpContent(map);
        log.info("PC端[/formatVideo - formatVideo] 返回值 {}", rsMap);
        return new ResponseEntity<>(rsMap, HttpStatus.OK);
    }


    @PostMapping(value = "/formatHomeImage")
    @Log("居家解约上传图片至MINIO")
    @ApiOperation("居家解约上传图片至MINIO")
    public ResponseEntity<Object> formatHomeImage (@RequestParam MultipartFile file, @RequestParam String fjlb, @RequestParam(required = false) String ywid) throws Exception {
        ywid = ywid == null ? "" : ywid;
        FileUtil.checkSize(properties.getMaxSize(), file.getSize());
        // 判断文件是否为图片
        String suffix = FileUtil.getExtensionName(file.getOriginalFilename());

        if(!FileUtil.IMAGE.equals(FileUtil.getFileType(suffix))){
            throw new BadRequestException("只能上传jpg png图片");
        }

        log.info("文件信息：title={}, size={}", file.getOriginalFilename(), file.getSize());

        Map<String, String> map = MinioUtils.upload(file);

        LocalStorage localStorage = new LocalStorage(
                file.getOriginalFilename(),
                FileUtil.getFileNameNoEx(file.getOriginalFilename()),
                suffix,
                map.get("url"),
                file.getContentType(),
                FileUtil.getSize(file.getSize()),
                fjlb,
                ywid,
                map.get("url2"),
                map.get("url3")
        );

        LocalStorage localStorage1 = localStorageService.minioCreate(localStorage);
        map.put("id", String.valueOf(localStorage1.getId()));
        Map<String,Object> rsMap = PageUtil.toMpContent(map);
        log.info("PC端[/formatHomeImage - formatHomeImage] 返回值 {}", rsMap);
        return new ResponseEntity<>(rsMap, HttpStatus.OK);
    }

    @PostMapping(value = "/faceImage")
    @Log("上传人脸识别图片至MINIO")
    @ApiOperation("上传人脸识别图片至MINIO")
    public ResponseEntity<Object> faceImage(@RequestParam MultipartFile file, @RequestParam String fjlb, @RequestParam(required = false) String ywid) throws Exception {
        ywid = ywid == null ? "" : ywid;
        FileUtil.checkSize(properties.getMaxSize(), file.getSize());
        // 判断文件是否为图片
        String suffix = FileUtil.getExtensionName(file.getOriginalFilename());

        if(!FileUtil.IMAGE.equals(FileUtil.getFileType(suffix))){
            throw new BadRequestException("只能上传jpg png图片");
        }

        log.info("文件信息：title={}, size={}", file.getOriginalFilename(), file.getSize());

        Map<String, String> map = MinioUtils.uploadNurseList(file);

        LocalStorage localStorage = new LocalStorage(
                map.get("filename"),
                FileUtil.getFileNameNoEx(file.getOriginalFilename()),
                suffix,
                map.get("url"),
                file.getContentType(),
                FileUtil.getSize(file.getSize()),
                fjlb,
                ywid,
                map.get("url2"),
                map.get("url3")
        );

        LocalStorage localStorage1 = localStorageService.minioCreate(localStorage);
        map.put("id", String.valueOf(localStorage1.getId()));
        Map<String,Object> rsMap = PageUtil.toMpContent(map);
        log.info("PC端[/formatHomeImage - formatHomeImage] 返回值 {}", rsMap);
        return new ResponseEntity<>(rsMap, HttpStatus.OK);
    }

    @PostMapping(value = "/uploadVideo")
    @Log("MINIO上传视频")
    @ApiOperation("MINIO上传视频")
    public ResponseEntity<Object> uploadVideo (@RequestParam MultipartFile file) throws Exception {
        FileUtil.checkSize(properties.getMaxSize(), file.getSize());
        // 判断文件是否为图片
        String suffix = FileUtil.getExtensionName(file.getOriginalFilename());
        if(!FileUtil.VIDEO.equals(FileUtil.getFileType(suffix))){
            throw new BadRequestException("只能上传视频");
        }
        Map<String, String> map = MinioUtils.upload(file);

        LocalStorage localStorage = new LocalStorage(
                map.get("filename"),
                FileUtil.getFileNameNoEx(file.getOriginalFilename()),
                suffix,
                map.get("url"),
                file.getContentType(),
                FileUtil.getSize(file.getSize())
        );
        localStorageService.minioCreate(localStorage);
        return new ResponseEntity<>(HttpStatus.CREATED);
    }

    @PostMapping(value = "/mp/uploadImages")
    @Log("移动端IO上传照片")
    @ApiOperation("移动端IO上传照片")
    public ResponseEntity<Object> uploadImages (@RequestParam MultipartFile[] files) throws Exception {
        log.info("移动端IO上传照片------------------", files);
        List list = new ArrayList<>();
        for(MultipartFile file : files) {
            FileUtil.checkSize(properties.getMaxSize(), file.getSize());
            // 判断文件是否为图片
            String suffix = FileUtil.getExtensionName(file.getOriginalFilename());
            if(!FileUtil.IMAGE.equals(FileUtil.getFileType(suffix))){
                throw new BadRequestException("只能上传图片");
            }
            Map<String, String> map = MinioUtils.upload(file);
            list.add(map);

            LocalStorage localStorage = new LocalStorage(
                    map.get("filename"),
                    FileUtil.getFileNameNoEx(file.getOriginalFilename()),
                    suffix,
                    map.get("url"),
                    file.getContentType(),
                    FileUtil.getSize(file.getSize())
            );
            localStorageService.minioCreate(localStorage);
        }

        Map<String,Object> rsMap = PageUtil.toMpContent(list);
        log.info("移动端[/mp/uploadImage - uploadMpImage] 返回值 {}", rsMap);
        return new ResponseEntity<>(rsMap, HttpStatus.OK);
    }


    @PostMapping(value = "/mp/uploadImage")
    @Log("移动端IO上传照片")
    @ApiOperation("移动端IO上传照片")
    public ResponseEntity<Object> uploadMpImage (@RequestParam MultipartFile file, @RequestParam String fjlb, @RequestParam(required = false) String ywid) throws Exception {

        if(ywid == null){
            ywid = "";
        }
        log.info("fjlb : {} ", fjlb);
        FileUtil.checkSize(properties.getMaxSize(), file.getSize());
        // 判断文件是否为图片
        String suffix = FileUtil.getExtensionName(file.getOriginalFilename());
        if(!FileUtil.IMAGE.equals(FileUtil.getFileType(suffix))){
            throw new BadRequestException("只能上传图片");
        }
        Map<String, String> map = MinioUtils.upload(file);

        LocalStorage localStorage = new LocalStorage(
                map.get("filename"),
                FileUtil.getFileNameNoEx(file.getOriginalFilename()),
                suffix,
                map.get("url"),
                file.getContentType(),
                FileUtil.getSize(file.getSize()),
                fjlb,
                ywid,
                map.get("url2"),
                map.get("url3")
        );
        LocalStorage localStorage1 = localStorageService.minioCreate(localStorage);
        map.put("id", String.valueOf(localStorage1.getId()));

        Map<String,Object> rsMap = PageUtil.toMpContent(map);
        log.info("移动端[/mp/uploadImage - uploadMpImage] 返回值 {}", rsMap);
        return new ResponseEntity<>(rsMap, HttpStatus.OK);
    }
    @PostMapping(value = "/mp/upload2Image")
    @Log("移动端IO上传照片")
    @ApiOperation("移动端IO上传照片")
    public ResponseEntity<Object> upload2Image (@RequestParam MultipartFile file, @RequestParam String fjlb, @RequestParam(required = false) String ywid) throws Exception {

        if(ywid == null){
            ywid = "";
        }
        log.info("fjlb : {} ", fjlb);
        FileUtil.checkSize(properties.getMaxSize(), file.getSize());
        // 判断文件是否为图片
        String suffix = FileUtil.getExtensionName(file.getOriginalFilename());
        if(!FileUtil.IMAGE.equals(FileUtil.getFileType(suffix))){
            throw new BadRequestException("只能上传图片");
        }
        Map<String, String> map = MinioUtils.upload(file);

        LocalStorage localStorage = new LocalStorage(
                map.get("filename"),
                FileUtil.getFileNameNoEx(file.getOriginalFilename()),
                suffix,
                map.get("url"),
                file.getContentType(),
                FileUtil.getSize(file.getSize()),
                fjlb,
                ywid,
                map.get("url2"),
                map.get("url3")
        );
        LocalStorage localStorage1 = localStorageService.minioCreate(localStorage);
        map.put("id", String.valueOf(localStorage1.getId()));

        Map<String, Object> tempMap = new HashMap<>();
        tempMap.put("imgsViewMap", map);
        tempMap.put("ImgsObject", localStorage1);

        Map<String,Object> rsMap = PageUtil.toMpContent(tempMap);
        log.info("移动端[/mp/uploadImage - uploadMpImage] 返回值 {}", rsMap);
        return new ResponseEntity<>(rsMap, HttpStatus.OK);
    }

    @PostMapping(value = "/mp/uploadVideo")
    @Log("移动端上传视频")
    @ApiOperation("移动端上传视频")
    public ResponseEntity<Object> uploadMpVideo (@RequestParam MultipartFile file, @RequestParam String fjlb, @RequestParam(required = false) String ywid) throws Exception {
        if(ywid == null){
            ywid = "";
        }

        FileUtil.checkSize(properties.getMaxSize(), file.getSize());
        // 判断文件是否为图片
        String suffix = FileUtil.getExtensionName(file.getOriginalFilename());
        if(!FileUtil.VIDEO.equals(FileUtil.getFileType(suffix))){
            throw new BadRequestException("只能上传视频");
        }
        Map<String, String> map = MinioUtils.upload(file);

        LocalStorage localStorage = new LocalStorage(
                map.get("filename"),
                FileUtil.getFileNameNoEx(file.getOriginalFilename()),
                suffix,
                map.get("url"),
                file.getContentType(),
                FileUtil.getSize(file.getSize()),
                fjlb,
                ywid,
                map.get("url2"),
                map.get("url3")
        );
        LocalStorage localStorage1 = localStorageService.minioCreate(localStorage);
        map.put("id", String.valueOf(localStorage1.getId()));
        Map<String,Object> rsMap = PageUtil.toMpContent(map);
        log.info("移动端[/mp/uploadVideo - uploadMpVideo] 返回值 {}", rsMap);
        return new ResponseEntity<>(rsMap, HttpStatus.OK);
    }

    @GetMapping(value = "/mp/getLocalStore")
    @Log("根据业务ID及业务类型查询")
    @ApiOperation("根据业务ID及业务类型查询")
    public ResponseEntity<Object> getLocalStore (String ywid, String fjlbs) throws Exception {
        return new ResponseEntity<>(PageUtil.toMpContent(localStorageService.findByYwidAndFjlb(ywid,fjlbs)), HttpStatus.OK);
    }


    @Log("删除文件")
    @DeleteMapping("/mp/deleteFile")
    @ApiOperation("多选删除")
    public ResponseEntity<Object> deleteFile(@RequestBody Long[] ids) {
        localStorageService.deleteAll(ids);
        return new ResponseEntity<>(PageUtil.toMpContent(new HashMap<String,Object>()),HttpStatus.OK);
    }
}
